package com.easyoffer.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easyoffer.annotation.RoleCheck;
import com.easyoffer.constant.UserConstant;
import com.easyoffer.model.entity.Question;
import com.easyoffer.service.QuestionBankQuestionService;
import com.easyoffer.service.QuestionBankService;
import com.easyoffer.service.QuestionService;
import com.easyoffer.service.UserService;
import com.easyoffer.common.ErrorCode;
import com.easyoffer.exception.BusinessException;
import com.easyoffer.model.dto.questionbankquestion.QuestionBankQuestionAddRequest;
import com.easyoffer.model.entity.QuestionBankQuestion;
import com.easyoffer.model.vo.UserVO;
import com.easyoffer.mapper.QuestionBankQuestionMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author 何文斌
* @description 针对表【question_bank_question(题库题目)】的数据库操作Service实现
* @createDate 2025-03-15 21:09:28
*/
@Service
@Slf4j
public class QuestionBankQuestionServiceImpl extends ServiceImpl<QuestionBankQuestionMapper, QuestionBankQuestion>
    implements QuestionBankQuestionService {
    @Autowired
    UserService userService;
    @Autowired
    @Lazy
    QuestionService questionService;
    @Autowired
    QuestionBankService questionBankService;

    @Override
    public Boolean addQuestionBankQuestion(QuestionBankQuestionAddRequest addRequest, HttpServletRequest request) {
        if (addRequest == null)
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        QuestionBankQuestion questionBankQuestion = new QuestionBankQuestion();
        BeanUtil.copyProperties(addRequest,questionBankQuestion);
        UserVO loginUser = (UserVO) StpUtil.getSession().get(UserConstant.USER_LOGIN_STATE);
        questionBankQuestion.setUserId(loginUser.getId());
        return this.save(questionBankQuestion) ;
    }

    /**
     * 批量添加题目到题库(*仅管理员可操作*)
     *
     * @param questionBankId 题库id
     * @param questionIdList 题目id集合
     * @param request        请求
     * @return 添加是否成功
     */
    @Override
    @RoleCheck(mustRole = "admin")
    public Boolean saveBatchToBank(Long questionBankId, List<Long> questionIdList, HttpServletRequest request) {
        //题库id和题目id参数为空
        if (questionBankId == null || CollUtil.isEmpty(questionIdList))
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        //题库不存在
        if (questionBankService.getById(questionBankId) == null)
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"该题库不存在");
        //拿到题目id集合中实际存在的题目id集合
        List<Long> existIds = questionService.list(new LambdaQueryWrapper<Question>()
                        .in(Question::getId, questionIdList)
                        .select(Question::getId))
                .stream()
                .map(Question::getId)
                .collect(Collectors.toList());
        if (CollUtil.isEmpty(existIds))
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"题目不存在");
        //检索已经添加到相关题库的题目id
        LambdaQueryWrapper<QuestionBankQuestion> queryAlredyWrapper =  new LambdaQueryWrapper<QuestionBankQuestion>()
                .eq(QuestionBankQuestion::getQuestionBankId,questionBankId)
                .in(QuestionBankQuestion::getQuestionId,existIds)
                .select(QuestionBankQuestion::getQuestionId);
        List<Long> alreadyInsertIds = this
                .list(queryAlredyWrapper)
                .stream()
                .map(QuestionBankQuestion::getQuestionId)
                .collect(Collectors.toList());
        List<Long> notInsertIds = existIds.stream().filter(
                existId -> !alreadyInsertIds.contains(existId)
        ).collect(Collectors.toList());

        Long userId = userService.getLoginUser(request).getId();
        int saveSize = 1000;
        int total = notInsertIds.size();
        for (int i = 0; i < total; i += saveSize){
            int end = Math.min(i + saveSize, notInsertIds.size());
            List<Long> subList = notInsertIds.subList(i, end);
            QuestionBankQuestionService service = (QuestionBankQuestionService) AopContext.currentProxy();
            service.saveBatchToBankMethod(questionBankId, subList, userId);
        }
        return true;
    }

    /**
     * 分批添加题目到题库方法
     *
     * @param questionBankId 题库id
     * @param questionIdList 题目id集合
     * @param userId         添加用户id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @RoleCheck(mustRole = "admin")
    public void saveBatchToBankMethod(Long questionBankId, List<Long> questionIdList, Long userId) {
        List<QuestionBankQuestion> saveList = new ArrayList<>();
        for (Long questionId : questionIdList) {
            QuestionBankQuestion questionBankQuestion = new QuestionBankQuestion();
            questionBankQuestion.setQuestionId(questionId);
            questionBankQuestion.setQuestionBankId(questionBankId);
            questionBankQuestion.setUserId(userId);
            saveList.add(questionBankQuestion);
        }
        //添加失败要抛出异常去回滚
        try{
            if (!this.saveBatch(saveList)){
                log.error("添加题目{}到题库{}失败",questionIdList,questionBankId);
                throw new BusinessException(ErrorCode.OPERATION_ERROR,"添加失败");
            }
        }catch (DuplicateKeyException e){
            System.out.println("【事务是否标记为回滚】" + TransactionSynchronizationManager.isCurrentTransactionReadOnly());
            // 输出：true（说明已被标记为回滚）
            log.error("重复添加题目{}到题库{}时连接数据库失败",questionIdList,questionBankId);
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "重复添加数据");
        } catch (DataAccessException e){
            log.error("添加题目{}到题库{}时连接数据库失败",questionIdList,questionBankId);
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "连接数据库失败");
        }
    }

    @Override
    public Boolean deleteQuestionBankQuestion(Long id) {
        return this.removeById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @RoleCheck(mustRole = "admin")
    public Boolean batchRemoveQuestionFromBank(Long questionBankId, List<Long> questionIdList, HttpServletRequest request) {
        if (questionBankId == null || CollUtil.isEmpty(questionIdList))
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"非法参数");
        if (questionBankService.getById(questionBankId) == null)
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"该题库不存在");
        for (Long removeId : questionIdList) {
            LambdaQueryWrapper<QuestionBankQuestion> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(QuestionBankQuestion::getQuestionBankId, questionBankId)
                    .eq(QuestionBankQuestion::getQuestionId, removeId);

            if (!this.remove(queryWrapper))
                throw new BusinessException(ErrorCode.OPERATION_ERROR,"删除失败");
        }
        return true;
    }
}




